#import "ZZNetWorker.h"
//#import "ZZNetWorker+generateSignature.h"
#import "ZZNetWorkRequest.h"
#import "NSObject+MJKeyValue.h"

@interface ZZNetWorker ()

@property (nonatomic, strong) ZZNetWorkerDefaultBlock defaultHandlerBlock;

@property (nonatomic, strong) NSMutableArray *requestArray;
@end

@implementation ZZNetWorker

- (NSMutableArray *)requestArray{
    if (!_requestArray) {
        _requestArray = [NSMutableArray array];
    }
    return _requestArray;
}

+ (instancetype)woker {
    
    static ZZNetWorker *_instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [[ZZNetWorker alloc]init];
        _instance.responseClass = [ZZNetWorkResponse class];
        _instance.paramHandler = [[ZZNetWorkParamHandler alloc] init];
        _instance.decode = [[ZZNetWorkDecode alloc] init];
        _instance.defaultRequestSerializer = [AFJSONRequestSerializer serializer];
        _instance.defaultResponseSerializer = [AFHTTPResponseSerializer serializer];
        _instance.tokenKey = @"Auth-Token";
    });
    return _instance;
}

+ (ZZNetWorkRequest *)GET{
    ZZNetWorkRequest *request = [ZZNetWorkRequest request];
    request.method = GET;
    [self configRequest:request];
    return request;
}

+ (ZZNetWorkRequest *)POST{
    ZZNetWorkRequest *request = [ZZNetWorkRequest request];
    request.method = POST;
    [self configRequest:request];
    return request;
}

+ (ZZNetWorkUploadRequest *)UPLOAD{
    ZZNetWorkUploadRequest *request = (ZZNetWorkUploadRequest *)[ZZNetWorkUploadRequest request];
    request.method = UPLOAD;
    [self configRequest:request];
    request.willHandlerParam = NO;
    return request;
}

+ (ZZNetWorkRequest *)DELETE{
    ZZNetWorkRequest *request = [ZZNetWorkRequest request];
    request.method = DELETE;
    [self configRequest:request];
    return request;
}

+ (ZZNetWorkRequest *)PUT{
    ZZNetWorkRequest *request = [ZZNetWorkRequest request];
    request.method = PUT;
    [self configRequest:request];
    return request;
}

+ (void)configRequest:(ZZNetWorkRequest *)request{
    ZZNetWorker *woker = [ZZNetWorker woker];
    request.authorization = woker.token;
    request.responseClass = woker.responseClass;
    request.paramHandler = woker.paramHandler;
    request.isShowErrorMessage = YES;
    request.willHandlerParam = YES;
    request.baseUrl = woker.baseUrl;
    request.manager = woker.manager;
#ifdef DEBUG
    request.isOpenLog = YES;
#else
    request.isOpenLog = NO;
#endif
}

- (NSURLSessionDataTask *)request:(ZZNetWorkRequest *)request{
    
    //接收、响应设置
    if (request.requestSerializer) {
        self.manager.requestSerializer = request.requestSerializer;
    }else if(self.manager.requestSerializer != self.defaultRequestSerializer){
        self.manager.requestSerializer = self.defaultRequestSerializer;
    }
    
    if (request.responseSerializer) {
        self.manager.responseSerializer = request.responseSerializer;
    }else if(self.manager.responseSerializer != self.defaultResponseSerializer){
        self.manager.responseSerializer = self.defaultResponseSerializer;
    }
    
    //set token
    if (request.authorization.length) {
        [self.manager.requestSerializer setValue:request.authorization forHTTPHeaderField:self.tokenKey];
        ZZLog(@"\n token: \n%@",request.authorization);
    }else{
        [self.manager.requestSerializer setValue:nil forHTTPHeaderField:self.tokenKey];
    }
    
    //初始化
    if (self.defaultHandlerBlock) {
        self.defaultHandlerBlock(self.manager, request);
    }
    
    //取消重复请求
    if (request.isCancelSameRequest){
        ZZNetWorkRequest *cancelTask = nil;
        for (ZZNetWorkRequest *req in self.requestArray) {
            NSString *url2 = req.task.originalRequest.URL.absoluteString;
            if ([url2 isEqualToString:request.url]){
                [req.task cancel];
                cancelTask = req;
                ZZLog(@"\n\n========= 取消请求 =========");
                ZZLog(@"---url      === %@",request.url);
                ZZLog(@"========= 取消请求 ========= \n\n");
            }
        }
        if (cancelTask) {
            [self.requestArray removeObject:cancelTask];
        }
    }
    
    [self.requestArray addObject:request];
  
    if (request.method == GET) {
        return [self GET:request];
    }else if (request.method == POST) {
        return [self POST:request];
    }else if (request.method == DELETE) {

    }else if (request.method == PUT) {

    }else if (request.method == UPLOAD) {
        return [self uploadFile:(ZZNetWorkUploadRequest *)request];
    }
    return nil;
}

- (NSURLSessionDataTask *)GET:(ZZNetWorkRequest *)request{

    id param = request.param;
    if (request.willHandlerParam && self.paramHandler) {
        param = [self.paramHandler handleParamWithRequest:request];
    }
    
    NSURLSessionDataTask *dataTask = [self.manager GET:request.url 
                                            parameters:param
                                               headers:request.headers
                                              progress:request.progress
                                               success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        
        ZZNetWorkResponse *responseModel = [self handerResult:task responseObject:responseObject error:nil request:request];
        
        request.completion(responseModel, nil);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        ZZNetWorkResponse *responseModel = [self handerResult:task responseObject:nil error:error request:request];
        request.completion(responseModel,error);
    }];
    
    return dataTask;
}

- (NSURLSessionDataTask *)POST:(ZZNetWorkRequest *)request{
    
    id param = request.param;
    if (request.willHandlerParam && self.paramHandler) {
        param = [self.paramHandler handleParamWithRequest:request];
    }
    
    NSURLSessionDataTask *dataTask = [self.manager POST:request.url 
                                             parameters:param
                                                headers:request.headers
                                               progress:request.progress
                                                success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        
        ZZNetWorkResponse *responseModel = [self handerResult:task responseObject:responseObject error:nil request:request];
        
        request.completion(responseModel, nil);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        
        ZZNetWorkResponse *responseModel = [self handerResult:task responseObject:nil error:error request:request];
        request.completion(responseModel,error);
    }];
    
    return dataTask;
}

- (NSURLSessionDataTask *)uploadFile:(ZZNetWorkUploadRequest *)request{
    
    id param = request.param;
    if (request.willHandlerParam && self.paramHandler) {
        param = [self.paramHandler handleParamWithRequest:request];
    }
    
    NSURLSessionDataTask *dataTask =  [self.manager POST:request.url 
                                              parameters:request.param
                                                 headers:request.headers
                               constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
       
       [formData appendPartWithFileData:request.data name:request.name fileName:request.fileName mimeType:request.mimeType];
       
    } progress:request.progress success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        
        ZZNetWorkResponse *responseModel = [self handerResult:task responseObject:responseObject error:nil request:request];
        request.completion(responseModel, nil);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        ZZNetWorkResponse *responseModel = [self handerResult:task responseObject:nil error:error request:request];
        request.completion(responseModel,error);
    }];
    
    return dataTask;
}


- (ZZNetWorkResponse *)handerResult:(NSURLSessionDataTask * _Nullable)task
      responseObject:(id  _Nullable)responseObject
               error:(NSError * _Nullable)error
             request:(ZZNetWorkRequest *)request{
    ZZNetWorkResponse *responseModel = nil;
    if (error) {
        responseModel = [[[request.responseClass class] alloc] init];
        responseModel.code = -1000;
        responseModel.msg = error.userInfo[NSLocalizedDescriptionKey];
        
        if (request.isOpenLog) {
            ZZLog(@"========= 开始打印 =========");
            ZZLog(@"---url   === %@",request.url);
            ZZLog(@"---param === %@",request.param);
            ZZLog(@"---error === %@",error.userInfo[@"com.alamofire.serialization.response.error.response"]);
            ZZLog(@"========= 结束打印 =========");
        }

    }else{
        NSDictionary *dic = [self.decode decodeToJson:responseObject];
        if (request.testData) {
            dic = request.testData;
        }
        responseModel = [[request response] setKeyValues:dic];
        
        if (request.isOpenLog) {
            ZZLog(@"========= 开始打印 =========");
            ZZLog(@"---url      === %@",request.url);
            ZZLog(@"---param    === %@",request.param);
            ZZLog(@"---response === %@",dic);
            ZZLog(@"---message  === %@",responseModel.msg);
            ZZLog(@"========= 结束打印 =========");
        }
    }

    [self.requestArray removeObject:request];
    
    [responseModel codeVerify:request];
    return responseModel;
}



/*
- (void)FormData:(NSString *)URLString parameters:(id)parameters finishBlock:(void (^)(id, NSError *))finishBlock {
    
    self.manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"text/plain", @"multipart/form-data", @"application/json", @"text/html", @"image/jpeg", @"image/png", @"application/octet-stream", @"text/json", nil];
    [self.manager POST:URLString parameters:@{} constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
        
        if ([parameters isKindOfClass:[NSDictionary class]]) {
            NSString *fileName = parameters[@"fileName"];
            id obj = parameters[@"data"];
            if ([obj isKindOfClass:[NSData class]]) {
                [formData appendPartWithFileData:obj name:@"file" fileName:fileName mimeType:@"application/octet-stream"];
            }
            
            
//            NSArray *keys = [parameters allKeys];
            
//            for (NSString *key in keys) {
//                id obj = parameters[key];
//
//                if ([obj isKindOfClass:[NSDictionary class]]) {
//                    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:obj options:NSJSONWritingPrettyPrinted error:nil];
//                    [formData appendPartWithFormData:jsonData name:key];
//                }else if ([obj isKindOfClass:[NSString class]]) {
//                    NSData *jsonData = [obj dataUsingEncoding:NSUTF8StringEncoding];
//                    [formData appendPartWithFormData:jsonData name:key];
//                }else if ([obj isKindOfClass:[NSData class]]) {
//                    [formData appendPartWithFormData:obj name:key];
//                    [formData appendPartWithFileData:obj name:@"file" fileName:@"" mimeType:@"application/octet-stream"];
//                }
//
//            }
        }

        
    } progress:^(NSProgress * _Nonnull uploadProgress) {
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSDictionary *dic = [ZZNetWorkHandler jsonFromResponseObject:responseObject];
        if (self.isOpenLog) {
            ZZLog(@"\n ZZNetWorker:\n url:%@ \n param:%@ \n response :%@ \n message = %@ \n",URLString,parameters,dic,dic[@"msg"]);
        }
        if (![self checkResult:dic]) {
            return ;
        }
        finishBlock(dic,nil);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        if (self.isOpenLog) {
            NSData *datae = error.userInfo[@"com.alamofire.serialization.response.error.data"] ;
            NSString *errorStr = [[ NSString alloc ] initWithData:datae encoding:NSUTF8StringEncoding];
            ZZLog(@"\n ZZNetWorker:\n  url:%@ \n param:%@ \n error:%@ \n ",URLString,parameters,errorStr);
        }
        finishBlock(nil,error);
    }];
    
}
 */

 

- (AFHTTPSessionManager *)manager {
    if (_manager == nil) {
        _manager = [AFHTTPSessionManager manager];
        _manager.requestSerializer.timeoutInterval = 15;
        
//        AFSecurityPolicy *securityPolicy = [AFSecurityPolicy defaultPolicy];
//        securityPolicy.validatesDomainName = NO;
//        securityPolicy.allowInvalidCertificates = YES;
//        _manager.securityPolicy = securityPolicy;
        __weak typeof(self) wkself = self;
        [_manager setDataTaskDidReceiveDataBlock:^(NSURLSession * _Nonnull session, NSURLSessionDataTask * _Nonnull dataTask, NSData * _Nonnull data) {
            for (ZZNetWorkRequest *req in wkself.requestArray) {
                if (dataTask == req.task && req.receiveData){
                    req.receiveData(session, dataTask, data);
                }
            }
        }];
    }
    return _manager;
}


- (ZZNetWorker *(^)(ZZNetWorkerManagerBlock))zz_manager{
    return ^id (ZZNetWorkerManagerBlock block){
        if(block) block(self.manager);
        return self;
    };
}

- (ZZNetWorker *(^)(ZZNetWorkerDefaultBlock))zz_defaultRequest{
    return ^id (ZZNetWorkerDefaultBlock block){
        self.defaultHandlerBlock = block;
        return self;
    };
}

- (void)showLoginViewController{
//    [self showMessage:@"登录信息已过期，请重新登录！"];
//    [[UserManager shareInstance] loginOut];
//    [AppLoginManager showLoginViewController];
    [self.manager.operationQueue cancelAllOperations];
}

@end

/*
 //分割符
 NSString *TWITTERFON_FORM_BOUNDARY = @"0xKhTmLbOuNdArY";
 //分界线 --AaB03x
 NSString *MPboundary=[[NSString alloc]initWithFormat:@"--%@",TWITTERFON_FORM_BOUNDARY];
 //结束符 AaB03x--
 NSString *endMPboundary=[[NSString alloc]initWithFormat:@"%@--",MPboundary];
 //http 参数body的字符串
 NSMutableString *paraBody=[[NSMutableString alloc]init];
 //参数的集合的所有key的集合
 NSArray *keys= [parameters allKeys];
 //遍历keys
 for(int i = 0; i < [keys count] ; i++)
 {
 //得到当前key
 NSString *key=[keys objectAtIndex:i];
 //添加分界线，换行
 [paraBody appendFormat:@"%@\r\n",MPboundary];
 //添加字段名称，换2行
 [paraBody appendFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n",key];
 //添加字段的值
 [paraBody appendFormat:@"%@\r\n",[parameters objectForKey:key]];
 
 NSLog(@"参数%@ == %@",key,[parameters objectForKey:key]);
 }
 
 //声明myRequestData，用来放入http body
 NSMutableData *myRequestData = [[NSMutableData alloc] init];
 //将body字符串转化为UTF8格式的二进制
 [myRequestData appendData:[paraBody dataUsingEncoding:NSUTF8StringEncoding]];
 
 //声明结束符：--AaB03x--
 NSString *end=[[NSString alloc]initWithFormat:@"\r\n%@",endMPboundary];
 //加入结束符--AaB03x--
 [myRequestData appendData:[end dataUsingEncoding:NSUTF8StringEncoding]];
 
 //设置HTTPHeader中Content-Type的值
 NSString *content=[[NSString alloc]initWithFormat:@"multipart/form-data; boundary=%@",TWITTERFON_FORM_BOUNDARY];
 //设置HTTPHeader
 [request setValue:content forHTTPHeaderField:@"Content-Type"];
 //设置Content-Length
 [request setValue:[NSString stringWithFormat:@"%lu", [myRequestData length]] forHTTPHeaderField:@"Content-Length"];
 //设置http body
 [request setHTTPBody:myRequestData];
 
 POST请求设置请求头
 POST数据请求中，会设置HTTPHeaderField，
 key:Content-Type,
 Value为下面三种：

 application/x-www-form-urlencoded（后台接收为分开的参数时，如?name=liyu&password=123）
 application/json（后台接收为json对象时）
 multipart/form-data（上传文件时）
 如果设置的类型与后台的不匹配，则会请求失败。
 
 */
